#!/usr/bin/env python
# -*-coding:utf-8-*-
# File    : har2request.py
# Date    : 2020-08-13
# Author  : Tom.Lee

import os
import logging
import datetime
import json
import autopep8
from jinja2 import Environment
import argparse

# 将模板压缩成单一字符的原因是方便打包
temp_str = '#!/usr/bin/env python\n# -*-coding:utf-8-*-\n# creat by har2py\n# Date {{ creatime.strftime("%Y-%m-%d %H:%M:%S") }}\n\nimport requests\nrequests.packages.urllib3.disable_warnings()\n\nsess = requests.session()\nheaders = {{headers}}\nurl = "{{url}}"\n\nsess.headers = headers\n\nparams = {{params | default(None)}}\njsondata = {{jsondata | default(None)}}\n{% if is_text_body %}\n'
t2 = "postdata = '''{{postdata}}'''\n{% else %}\npostdata = {{postdata | default(None)}}\n{% endif %}\n\n\nresp = sess.{{method | lower}}(url, verify=False, json=jsondata, data=postdata, params=params)\nprint(resp.text)\n"
temp_str += t2


class Har2py:
    def __init__(self, request_dict):
        self.url = request_dict["url"].split("?")[0]
        self.method = request_dict["method"]
        headers = self.dictlist_handle(request_dict["headers"])
        if headers.get("Content-Length"):
            headers.pop("Content-Length")
        self.headers = headers
        self.query = self.dictlist_handle(request_dict["queryString"])
        self.request_dict = request_dict
        self.is_text_body = False
        self.post_data = None
        self.json_data = None
        self.post_data_handle()

    @classmethod
    def dictlist_handle(cls, header_list):
        # 将key-value列表转化成字典结构
        dict_data = {}
        for head in header_list:
            dict_data[head["name"]] = head["value"]
        if dict_data:
            return dict_data

    def post_data_handle(self):
        # 处理post数据
        request_dict = self.request_dict
        body_data = request_dict["postData"].get("text", None)

        # 处理body，如果是json格式，则更新json数据
        try:
            json_data = json.loads(body_data)
        except json.decoder.JSONDecodeError:
            self.post_data = body_data
            if body_data:
                self.is_text_body = True
            else:
                self.post_data = None
        else:
            self.json_data = json_data
        # web表单处理
        post_form_data = request_dict["postData"].get("params", None)
        if post_form_data:
            post_data = self.dictlist_handle(post_form_data)
            self.post_data = post_data
            if len(post_data) == 1:
                if list(post_data.keys())[0] is None:
                    self.post_data = post_data[None]
                    self.is_text_body = True

    def render(self):
        env = Environment()
        temp = env.from_string(temp_str)
        res = temp.render(
            headers=self.headers,
            url=self.url,
            method=self.method,
            postdata=self.post_data,
            jsondata=self.json_data,
            params=self.query,
            is_text_body=self.is_text_body,
            creatime=datetime.datetime.now(),
        )
        # 自动进行pep8格式化
        res = autopep8.fix_code(res, options={"max_line_length": 100})
        return res


def genrate_file(harfile, output_dir, filename=None):
    fp = open(harfile, "r", encoding="utf-8")
    content = fp.read()

    # 处理bom
    if content.startswith(u"\ufeff"):
        content = content.encode("utf8")[3:].decode("utf8")

    log_dict = json.loads(content)
    request_list = log_dict["log"]["entries"]
    for req_dict in request_list:
        req_obj = Har2py(req_dict["request"])

        # 获取接口名，将其做为输出的文件名
        filename = req_obj.url.split("/")[-1]
        filename = filename.replace("/", "").replace(":", "")
        if not filename:
            filename = "undefined"
        count = 0
        # 如果存在同名文件，则在文件名后加1
        while os.path.isfile(os.path.join(output_dir, filename + ".py")):
            count += 1
            filename += str(count)
        filename = os.path.join(output_dir, filename + ".py")

        with open(filename, "w", encoding="utf-8") as fs:
            # 使用jinja2渲染模板生成脚本
            fs.write(req_obj.render())
        logging.info("gernerate in {}".format(filename))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-v", "--verbosity", help="show version", action="store_true")
    parser.add_argument("har", help="input file path")
    parser.add_argument("-o", "--outdir", help="output dir", default=os.getcwd())
    parser.add_argument("-s", "--sigle", help="output sigle file", default="")
    parser.add_argument(
        "--log-level", default="INFO", help="Specify logging level, default is INFO."
    )
    args = parser.parse_args()

    log_level = getattr(logging, args.log_level.upper())
    logging.basicConfig(level=log_level)
    genrate_file(args.har, args.outdir, args.sigle)


if __name__ == "__main__":
    main()
